home *** CD-ROM | disk | FTP | other *** search
/ Greenhouse Effect Detection Expriment / NASA Greenhouse Effect Detection Expriment 1992 - Disc 2.iso / software / dos / cdf22pc / src / lib / cdfput.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-13  |  26.0 KB  |  916 lines

  1. /******************************************************************************
  2. *
  3. *  NSSDC/CDF                                           CDF 'put' operations.
  4. *
  5. *  Version 1.0, 14-Feb-92, ST Systems (STX)
  6. *
  7. *  Modification history:
  8. *
  9. *   V1.0  14-Feb-92, J Love        Original version (was part of `cdflib.c').
  10. *
  11. ******************************************************************************/
  12.  
  13. #include "cdflib.h"
  14.  
  15. /******************************************************************************
  16. * CDFput.
  17. ******************************************************************************/
  18.  
  19. CDFstatus CDFput (ap, item, fnc)
  20. va_list *ap;
  21. long item;
  22. long *fnc;
  23. {
  24. CDFstatus Pstatus = CDF_OK;
  25. CDFstatus Tstatus;
  26.  
  27. switch (item) {
  28.   case CDF_ARRAY_: {
  29.     long numDims;
  30.     long *dimSizes;
  31.     long i;
  32.     long Nbytes;
  33.  
  34.     numDims = va_arg (*ap, long);
  35.     dimSizes = va_arg (*ap, long *);
  36.  
  37.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  38.     if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  39.     if (_CURcdf->GDR.NumVar > 0) return CANNOT_CHANGE;
  40.     if (numDims < 0 || numDims > CDF_MAX_DIMS) return
  41.      BAD_NUM_DIMS;
  42.     for (i = 0; i < numDims; i++)
  43.        if (dimSizes[i] < 1) return BAD_DIM_SIZE;
  44.  
  45.     if (_CURcdf->status == CDF_READ_ONLY) {
  46.       Tstatus = ReopenCDFforWrite (_CURcdf);
  47.       STATUSdisp (Tstatus, Pstatus);
  48.     }
  49.  
  50.     if (numDims != _CURcdf->GDR.NumDims) {
  51.       /*** mark current GDR as unused ***/
  52.  
  53.       WASTErecord (_CURcdf->fp, _CURcdf->GDRoffset,
  54.      _CURcdf->GDR.RecordSize);
  55.  
  56.       /*** allocate new GDR (and point CDR to it) ***/
  57.  
  58.       _CURcdf->GDRoffset = _CURcdf->GDR.eof;
  59.       _CURcdf->CDR.GDRoffset = _CURcdf->GDRoffset;
  60.       _CURcdf->GDR.RecordSize = GDR_BASE_SIZE +
  61.         numDims*sizeof(Int32);
  62.       _CURcdf->GDR.eof += _CURcdf->GDR.RecordSize;
  63.     }
  64.  
  65.     _CURcdf->GDR.NumDims = numDims;
  66.  
  67.     if (_CURcdf->GDR.DimSizes != NULL)
  68.       free (_CURcdf->GDR.DimSizes);
  69.  
  70.     if (numDims > 0) {
  71.       _CURcdf->GDR.DimSizes = (Int32 *) malloc (numDims * sizeof(Int32));
  72.       if (_CURcdf->GDR.DimSizes == NULL) return BAD_MALLOC;
  73.       for (i = 0; i < numDims; i++)
  74.          _CURcdf->GDR.DimSizes[i] = dimSizes[i];
  75.     }
  76.     else
  77.       _CURcdf->GDR.DimSizes = NULL;
  78.  
  79.     /*** the following are reset whenever the ARRAY is changed ***/
  80.  
  81.     _CURcdf->recnum = 0;
  82.     _CURcdf->reccount = 1;
  83.     _CURcdf->recinterval = 1;
  84.  
  85.     if (_CURcdf->indices != NULL) free (_CURcdf->indices);
  86.     if (_CURcdf->counts != NULL) free (_CURcdf->counts);
  87.     if (_CURcdf->intervals != NULL) free (_CURcdf->intervals);
  88.  
  89.     if (numDims > 0) {
  90.       Nbytes = numDims * sizeof(long);
  91.  
  92.       _CURcdf->indices = (long *) malloc (Nbytes);
  93.       if (_CURcdf->indices == NULL) return BAD_MALLOC;
  94.       _CURcdf->counts = (long *) malloc (Nbytes);
  95.       if (_CURcdf->counts == NULL) return BAD_MALLOC;
  96.       _CURcdf->intervals = (long *) malloc (Nbytes);
  97.       if (_CURcdf->intervals == NULL) return BAD_MALLOC;
  98.  
  99.       for (i = 0; i < numDims; i++) {
  100.          _CURcdf->indices[i] = 0;
  101.          _CURcdf->counts[i] = 1;
  102.          _CURcdf->intervals[i] = 1;
  103.       }
  104.     }
  105.  
  106.     break;
  107.   }
  108.   case CDF_ENCODING_: {
  109.     long encoding;
  110.     long actualEncoding;
  111.     struct attrSTRUCT *Attr;
  112.     struct varSTRUCT *Var;
  113.  
  114.     encoding = va_arg (*ap, long);
  115.  
  116.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  117.     if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  118.  
  119.     /*** can't change if any variables have been written
  120.          to (including fill values) ***/
  121.  
  122.     Var = _CURcdf->varHead;
  123.     while (Var != NULL) {
  124.       if (Var->VDR.MaxRec > -1 || bitset(Var->VDR.Flags,VAR_FILLVALUE_BIT)) {
  125.         return CANNOT_CHANGE;
  126.       }
  127.       Var = Var->varNext;
  128.     }
  129.  
  130.     /*** can't change if any attribute entries have been Put ***/
  131.  
  132.     Attr = _CURcdf->attrHead;
  133.     while (Attr != NULL) {
  134.       if (Attr->ADR.NumEntries > 0) return CANNOT_CHANGE;
  135.       Attr = Attr->attrNext;
  136.     }
  137.  
  138.     if ( ! validEncoding(encoding,&actualEncoding)) return BAD_ENCODING;
  139.  
  140.     if (_CURcdf->status == CDF_READ_ONLY) {
  141.       Tstatus = ReopenCDFforWrite (_CURcdf);
  142.       STATUSdisp (Tstatus, Pstatus);
  143.     }
  144.  
  145.     _CURcdf->CDR.Encoding = actualEncoding;
  146.  
  147.     break;
  148.   }
  149.   case CDF_MAJORITY_: {
  150.     long        majority;
  151.     struct varSTRUCT *Var;
  152.  
  153.     majority = va_arg (*ap,long);
  154.  
  155.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  156.     if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  157.  
  158.     Var = _CURcdf->varHead;
  159.     while (Var != NULL) {
  160.       if (Var->VDR.MaxRec > -1) return CANNOT_CHANGE;
  161.       Var = Var->varNext;
  162.     }
  163.  
  164.     if (majority != ROW_MAJOR && majority != COL_MAJOR) return BAD_MAJORITY;
  165.  
  166.     if (_CURcdf->status == CDF_READ_ONLY) {
  167.       Tstatus = ReopenCDFforWrite (_CURcdf);
  168.       STATUSdisp (Tstatus, Pstatus);
  169.     }
  170.  
  171.     if (majority == ROW_MAJOR)
  172.       setbit(_CURcdf->CDR.Flags,CDF_MAJORITY_BIT);
  173.     else
  174.       clrbit(_CURcdf->CDR.Flags,CDF_MAJORITY_BIT);
  175.  
  176.     break;
  177.   }
  178.   case CDF_FORMAT_: {
  179.     long        format;
  180.  
  181.     format = va_arg (*ap,long);
  182.  
  183.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  184.     if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  185.     if(_CURcdf->GDR.NumVar > 0) return CANNOT_CHANGE;
  186.     if (format != SINGLE_FILE && format != MULTI_FILE) return BAD_FORMAT;
  187.  
  188.     if (_CURcdf->status == CDF_READ_ONLY) {
  189.       Tstatus = ReopenCDFforWrite (_CURcdf);
  190.       STATUSdisp (Tstatus, Pstatus);
  191.     }
  192.  
  193.     if (format == SINGLE_FILE)
  194.       setbit(_CURcdf->CDR.Flags,CDF_FORMAT_BIT);
  195.     else
  196.       clrbit(_CURcdf->CDR.Flags,CDF_FORMAT_BIT);
  197.  
  198.     break;
  199.   }
  200.   case VAR_NAME_: {
  201.     char *varName;
  202.     char tmpname[CDF_VAR_NAME_LEN+1];
  203.     long i;
  204.  
  205.     varName = va_arg (*ap, char *);
  206.  
  207.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  208.     if (_CURcdf->CURvar == NULL) return NO_VAR_SELECTED;
  209.     if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  210.  
  211.     if (strlen(varName) > CDF_VAR_NAME_LEN) {
  212.       strncpy (tmpname, varName, CDF_VAR_NAME_LEN);
  213.       tmpname[CDF_VAR_NAME_LEN] = NUL;
  214.       STATUSdisp (VAR_NAME_TRUNC, Pstatus);
  215.     }
  216.     else
  217.       strcpy (tmpname, varName);
  218.  
  219.     if ( ! validVarName(tmpname)) return BAD_VAR_NAME;
  220.  
  221.     for (i = 0; i < CDF_MAX_VARS; i++)
  222.        if (_CURcdf->var[i] != NULL)
  223.           if (strcmpITB(_CURcdf->var[i]->VDR.Name,tmpname) == 0)
  224.              return VAR_EXISTS;
  225.  
  226.     if (_CURcdf->status == CDF_READ_ONLY) {
  227.       Tstatus = ReopenCDFforWrite (_CURcdf);
  228.       STATUSdisp (Tstatus, Pstatus);
  229.     }
  230.  
  231.     strcpy (_CURcdf->CURvar->VDR.Name, tmpname);
  232.  
  233.     break;
  234.   }
  235.   case VAR_DATASPEC_: {
  236.     long dataType;
  237.     long numElements;
  238.     struct varSTRUCT *Var;
  239.  
  240.     dataType = va_arg (*ap, long);
  241.     numElements = va_arg (*ap, long);
  242.  
  243.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  244.     if (_CURcdf->CURvar == NULL) return NO_VAR_SELECTED;
  245.     if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  246.     if ( ! validDataType(dataType)) return BAD_DATA_TYPE;
  247.     if (numElements < 1) return BAD_NUM_ELEMS;
  248.  
  249.     if (dataType != CDF_CHAR && dataType != CDF_UCHAR)
  250.       if (numElements != 1) return BAD_NUM_ELEMS;
  251.  
  252.     Var = _CURcdf->CURvar;
  253.  
  254.     /***********************************************************
  255.     * If the data types are not equivalent or the number of
  256.     * elements are different, then check for the following:
  257.     *  1) if any records have been written
  258.     *  2) if a fill value has been specified
  259.     * If either is true, then the data spec. cannot be changed.
  260.     ***********************************************************/
  261.  
  262.     if ((_CDFequivTypes[dataType] !=
  263.         _CDFequivTypes[Var->VDR.DataType]) ||
  264.         numElements != Var->VDR.NumElem) {
  265.       if (Var->VDR.MaxRec > -1) return CANNOT_CHANGE;
  266.       if (bitset(Var->VDR.Flags,VAR_FILLVALUE_BIT)) return CANNOT_CHANGE;
  267.     }
  268.  
  269.     if (_CURcdf->status == CDF_READ_ONLY) {
  270.       Tstatus = ReopenCDFforWrite (_CURcdf);
  271.       STATUSdisp (Tstatus, Pstatus);
  272.     }
  273.  
  274.     Var->VDR.DataType = dataType;
  275.     Var->VDR.NumElem = numElements;
  276.  
  277.     calcVarParms (_CURcdf, Var);            /* recalculate */
  278.  
  279.     break;
  280.   }
  281.   case VAR_RECVARY_: {
  282.     long recVariance;
  283.  
  284.     recVariance = va_arg (*ap, long);
  285.  
  286.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  287.     if (_CURcdf->CURvar == NULL) return NO_VAR_SELECTED;
  288.     if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  289.  
  290.     /* Can't change if any records have been Put */
  291.  
  292.     if (_CURcdf->CURvar->VDR.MaxRec > -1) return CANNOT_CHANGE;
  293.  
  294.     if (_CURcdf->status == CDF_READ_ONLY) {
  295.       Tstatus = ReopenCDFforWrite (_CURcdf);
  296.       STATUSdisp (Tstatus, Pstatus);
  297.     }
  298.  
  299.     if (recVariance)
  300.        setbit(_CURcdf->CURvar->VDR.Flags,VAR_RECVARY_BIT);
  301.     else
  302.        clrbit(_CURcdf->CURvar->VDR.Flags,VAR_RECVARY_BIT);
  303.  
  304.     calcVarParms (_CURcdf, _CURcdf->CURvar);    /* recalculate */
  305.  
  306.     break;
  307.   }
  308.   case VAR_DIMVARYS_: {
  309.     long *dimVarys;
  310.     long i;
  311.  
  312.     dimVarys = va_arg (*ap, long *);
  313.  
  314.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  315.     if (_CURcdf->CURvar == NULL) return NO_VAR_SELECTED;
  316.     if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  317.  
  318.     /* Can't change if any records have been Put */
  319.  
  320.     if (_CURcdf->CURvar->VDR.MaxRec > -1) return CANNOT_CHANGE;
  321.  
  322.     if (_CURcdf->status == CDF_READ_ONLY) {
  323.       Tstatus = ReopenCDFforWrite (_CURcdf);
  324.       STATUSdisp (Tstatus, Pstatus);
  325.     }
  326.  
  327.     for (i = 0; i < _CURcdf->GDR.NumDims; i++)
  328.        if (dimVarys[i])
  329.           _CURcdf->CURvar->VDR.DimVarys[i] = VARY;
  330.        else
  331.           _CURcdf->CURvar->VDR.DimVarys[i] = NOVARY;
  332.  
  333.     calcVarParms (_CURcdf, _CURcdf->CURvar);    /* recalculate */
  334.  
  335.     break;
  336.   }
  337.   case VAR_FILLVALUE_: {
  338.     void *fillValue;
  339.     struct varSTRUCT *Var;
  340.     struct varSTRUCT *prevVar;
  341.  
  342.     fillValue = va_arg (*ap, void *);
  343.  
  344.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  345.     if (_CURcdf->CURvar == NULL) return NO_VAR_SELECTED;
  346.     if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  347.  
  348.     if (_CURcdf->status == CDF_READ_ONLY) {
  349.       Tstatus = ReopenCDFforWrite (_CURcdf);
  350.       STATUSdisp (Tstatus, Pstatus);
  351.     }
  352.  
  353.     Var = _CURcdf->CURvar;
  354.  
  355.     if (bitset(Var->VDR.Flags,VAR_FILLVALUE_BIT))
  356.       memmove (Var->VDR.FillValue, fillValue, Var->NvalueBytes);
  357.     else {
  358.       setbit (Var->VDR.Flags, VAR_FILLVALUE_BIT);
  359.       Var->VDR.FillValue = (void *) malloc (Var->NvalueBytes);
  360.       if (Var->VDR.FillValue == NULL) return BAD_MALLOC;
  361.       memmove (Var->VDR.FillValue, fillValue, Var->NvalueBytes);
  362.  
  363.       /*********************************************************
  364.       * If this VDR is the last record in the .cdf file, then
  365.       * just extend the record.  Otherwise, waste this VDR and
  366.       * create a new one.  This is checked because it is very
  367.       * likely that the fill value will be specified soon after
  368.       * the variable is created.
  369.       *********************************************************/
  370.  
  371.       if (Var->VDRoffset + Var->VDR.RecordSize == _CURcdf->GDR.eof) {
  372.         Var->VDR.RecordSize += Var->NvalueBytes;
  373.         _CURcdf->GDR.eof += Var->NvalueBytes;
  374.       }
  375.       else {
  376.         WASTErecord (_CURcdf->fp, Var->VDRoffset,
  377.         Var->VDR.RecordSize);
  378.         Var->VDRoffset = _CURcdf->GDR.eof;
  379.  
  380.         FINDprevVar (_CURcdf, Var, prevVar);
  381.  
  382.         if (prevVar == NULL)
  383.           _CURcdf->GDR.VDRhead = Var->VDRoffset;
  384.         else
  385.           prevVar->VDR.VDRnext = Var->VDRoffset;
  386.  
  387.         Var->VDR.RecordSize += Var->NvalueBytes;
  388.         _CURcdf->GDR.eof += Var->VDR.RecordSize;
  389.       }
  390.     }
  391.  
  392.     break;
  393.   }
  394.   case VAR_INITIALRECS_: {
  395.     long NinitialRecs;
  396.     long phyRecNum;
  397.     struct varSTRUCT *Var;
  398.  
  399.     NinitialRecs = va_arg (*ap, long);
  400.  
  401.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  402.     if (_CURcdf->CURvar == NULL) return NO_VAR_SELECTED;
  403.     if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  404.  
  405.     /* Can't set if any records have been Put */
  406.  
  407.     if (_CURcdf->CURvar->VDR.MaxRec > -1) return CANNOT_CHANGE;
  408.  
  409.     if (_CURcdf->status == CDF_READ_ONLY) {
  410.       Tstatus = ReopenCDFforWrite (_CURcdf);
  411.       STATUSdisp (Tstatus, Pstatus);
  412.     }
  413.  
  414.     if (NinitialRecs < 1) return BAD_INITIAL_RECS;
  415.  
  416.     Var = _CURcdf->CURvar;
  417.  
  418.     if (Var->status == VAR_CLOSED) {
  419.       Tstatus = OpenVar (_CURcdf, Var);
  420.       STATUSdisp (Tstatus, Pstatus);
  421.     }
  422.   
  423.     if (bitset(Var->VDR.Flags,VAR_RECVARY_BIT))
  424.       phyRecNum = NinitialRecs - 1;
  425.     else
  426.       phyRecNum = 0;
  427.  
  428.     Tstatus = AllocateRecords (_CURcdf, Var, phyRecNum, TRUE);
  429.     STATUSdisp (Tstatus, Pstatus);
  430.  
  431.     Var->VDR.MaxRec = phyRecNum;
  432.  
  433.     if (Var->VDR.MaxRec > _CURcdf->GDR.MaxRec)
  434.       _CURcdf->GDR.MaxRec = Var->VDR.MaxRec;
  435.  
  436.     break;
  437.   }
  438.   case VAR_EXTENDRECS_: {
  439.     long NextendRecs;
  440.  
  441.     NextendRecs = va_arg (*ap, long);
  442.  
  443.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  444.     if (_CURcdf->CURvar == NULL) return NO_VAR_SELECTED;
  445.     if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  446.  
  447.     if (_CURcdf->status == CDF_READ_ONLY) {
  448.       Tstatus = ReopenCDFforWrite (_CURcdf);
  449.       STATUSdisp (Tstatus, Pstatus);
  450.     }
  451.  
  452.     if (NextendRecs < 0) return BAD_EXTEND_RECS;
  453.       /* 0 is valid meaning that the default is to be used */
  454.  
  455.     _CURcdf->CURvar->VDR.NextendRecs = NextendRecs;
  456.     break;
  457.   }
  458.   case VAR_DATA_: {
  459.     long offset, phyRecNum, recOffset, indicesOffset;
  460.     long N;
  461.     char *value;
  462.     struct varSTRUCT *Var;
  463.  
  464.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  465.     if (_CURcdf->CURvar == NULL) return NO_VAR_SELECTED;
  466.  
  467.     if (_CURcdf->status == CDF_READ_ONLY) {
  468.       Tstatus = ReopenCDFforWrite (_CURcdf);
  469.       STATUSdisp (Tstatus, Pstatus);
  470.     }
  471.  
  472.     Var = _CURcdf->CURvar;
  473.  
  474.     if (Var->status == VAR_CLOSED) {
  475.       Tstatus = OpenVar (_CURcdf, Var);
  476.       STATUSdisp (Tstatus, Pstatus);
  477.     }
  478.  
  479.     Var->accessed_at = _CDFpseudo_clock++;
  480.  
  481.     value = va_arg (*ap, char *);
  482.  
  483.     /************************************************************
  484.     * Compute physical record number.
  485.     ************************************************************/
  486.  
  487.     if (bitclr(Var->VDR.Flags,VAR_RECVARY_BIT))
  488.       phyRecNum = 0;
  489.     else
  490.       phyRecNum = _CURcdf->recnum;
  491.  
  492.     /************************************************************
  493.     * Allocate records if necessary.
  494.     ************************************************************/
  495.  
  496.     if (Var->VDR.MaxRec < phyRecNum) {
  497. #if defined(vms)
  498.       /*** CAN'T EXTEND A V1 VECTOR FILE ***/
  499.       if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  500. #endif
  501.       Tstatus = AllocateRecords (_CURcdf, Var, phyRecNum, FALSE);
  502.       STATUSdisp (Tstatus, Pstatus);
  503.  
  504.       Var->VDR.MaxRec = phyRecNum;
  505.  
  506.       if (Var->VDR.MaxRec > _CURcdf->GDR.MaxRec)
  507.     _CURcdf->GDR.MaxRec = Var->VDR.MaxRec;
  508.     }
  509.  
  510.     /************************************************************
  511.     * Put variable data value.
  512.     ************************************************************/
  513.  
  514.     if (bitclr(_CURcdf->CDR.Flags,CDF_FORMAT_BIT))
  515.       recOffset = phyRecNum * Var->NphyRecBytes;
  516.     else
  517.       SINGLErecOffsetB (Var, phyRecNum, recOffset);
  518.  
  519.     INDICESoffsetB (_CURcdf->GDR.NumDims, Var, _CURcdf->indices,
  520.                     indicesOffset);
  521.     offset = recOffset + indicesOffset;
  522.  
  523. #if defined(sun) | defined(MIPSEB) | defined(IBMRS) | defined(HP)
  524.     Seek (Var->fp, offset, SEEK_SET);
  525.     N = putbytes (Var->NvalueBytes, value, Var->fp);
  526.     if (N != Var->NvalueBytes) return VAR_WRITE_ERROR;
  527. #endif
  528.  
  529. #if defined(vax) | defined(MIPSEL) | defined(__IBMPC__)
  530.     if (_CURcdf->CDR.Encoding == NETWORK_ENCODING) {
  531.       void *tmpbuffer;
  532.       double xdrbuffer;
  533.  
  534.       if (Var->NvalueBytes > sizeof(xdrbuffer)) {
  535.         tmpbuffer = (void *) malloc (Var->NvalueBytes);
  536.         if (tmpbuffer == NULL) return BAD_MALLOC;
  537.       }
  538.       else
  539.         tmpbuffer = (void *) &xdrbuffer;
  540.  
  541.       xdr_encode (Var->VDR.DataType, Var->VDR.NumElem, value, tmpbuffer);
  542.  
  543.       Seek (Var->fp, offset, SEEK_SET);
  544.       N = putbytes (Var->NvalueBytes, tmpbuffer, Var->fp);
  545.       if (N != Var->NvalueBytes) {
  546.         if (tmpbuffer != (void *) &xdrbuffer) free (tmpbuffer);
  547.         return VAR_WRITE_ERROR;
  548.       }
  549.  
  550.       if (tmpbuffer != (void *) &xdrbuffer) free (tmpbuffer);
  551.     }
  552.     else {        /* HOST encoding */
  553.       Seek (Var->fp, offset, SEEK_SET);
  554.       N = putbytes (Var->NvalueBytes, value, Var->fp);
  555.       if (N != Var->NvalueBytes) return VAR_WRITE_ERROR;
  556.     }
  557. #endif
  558.     break;
  559.   }
  560.   case VAR_HYPERDATA_: {
  561.     long phyStartRecN, phyEndRecN;
  562.     char *buffer;
  563.     long i;
  564.     struct varSTRUCT *Var;
  565.     long Nvalues, Nbytes;
  566.  
  567.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  568.     if (_CURcdf->CURvar == NULL) return NO_VAR_SELECTED;
  569.  
  570.     if (_CURcdf->status == CDF_READ_ONLY) {
  571.       Tstatus = ReopenCDFforWrite (_CURcdf);
  572.       STATUSdisp (Tstatus, Pstatus);
  573.     }
  574.  
  575.     Var = _CURcdf->CURvar;
  576.  
  577.     if (Var->status == VAR_CLOSED) {
  578.       Tstatus = OpenVar (_CURcdf, Var);
  579.       STATUSdisp (Tstatus, Pstatus);
  580.     }
  581.   
  582.     Var->accessed_at = _CDFpseudo_clock++;
  583.  
  584.     buffer = va_arg (*ap, char *);
  585.  
  586. #if FULL_ERROR_CHECKING
  587.     for (i = 0; i < _CURcdf->GDR.NumDims; i++)
  588.        if (_CURcdf->indices[i] +
  589.            ((_CURcdf->counts[i] - 1) *
  590.         _CURcdf->intervals[i]) >= _CURcdf->GDR.DimSizes[i]) return
  591.                                 BAD_DIM_INDEX;
  592.  
  593. #if defined(__MSDOS__)
  594.     Nvalues = _CURcdf->reccount;
  595.     for (i = 0; i < _CURcdf->GDR.NumDims; i++) Nvalues *= _CURcdf->counts[i];
  596.     Nbytes = Nvalues * Var->VDR.NumElem * _CDFelemSizes[Var->VDR.DataType];
  597.     if (Nbytes > (long) 65535) return IBM_PC_OVERFLOW;
  598. #endif
  599. #endif
  600.  
  601.     /************************************************************
  602.     * Compute physical record numbers (start and end).
  603.     ************************************************************/
  604.  
  605.     if (bitclr(Var->VDR.Flags,VAR_RECVARY_BIT)) {
  606.       phyStartRecN = 0;
  607.       phyEndRecN = 0;
  608.     }
  609.     else {
  610.       phyStartRecN = _CURcdf->recnum;
  611.       phyEndRecN = phyStartRecN + (_CURcdf->reccount-1) * _CURcdf->recinterval;
  612.     }
  613.  
  614.     /************************************************************
  615.     * Allocate records if necessary.
  616.     ************************************************************/
  617.  
  618.     if (Var->VDR.MaxRec < phyEndRecN) {
  619. #if defined(vms)
  620.       /*** CAN'T EXTEND A V1 VECTOR FILE ***/
  621.       if (_CURcdf->CDR.Version == 1)
  622.         return ILLEGAL_ON_V1_CDF;
  623. #endif
  624.       Tstatus = AllocateRecords (_CURcdf, Var, phyEndRecN, FALSE);
  625.       STATUSdisp (Tstatus, Pstatus);
  626.  
  627.       Var->VDR.MaxRec = phyEndRecN;
  628.  
  629.       if (Var->VDR.MaxRec > _CURcdf->GDR.MaxRec)
  630.         _CURcdf->GDR.MaxRec = Var->VDR.MaxRec;
  631.     }
  632.  
  633.     /************************************************************
  634.     * Put variable data value(s).
  635.     ************************************************************/
  636.  
  637.     if (bitset(_CURcdf->CDR.Flags,CDF_MAJORITY_BIT))
  638.       Tstatus = HyperAccess (Var, buffer, TRUE, FALSE);
  639.     else
  640.       Tstatus = HyperAccess (Var, buffer, FALSE, FALSE);
  641.     STATUSdisp (Tstatus, Pstatus);
  642.  
  643.     break;
  644.   }
  645.   case VAR_SEQDATA_: {
  646.     struct varSTRUCT *Var;
  647.     void *value;
  648.     long N;
  649.     long recOffset;
  650.     long offset;
  651.     long recN;  /* record number value is in */
  652.  
  653.     value = va_arg (*ap, char *);
  654.  
  655.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  656.     if (_CURcdf->CURvar == NULL) return NO_VAR_SELECTED;
  657.  
  658.     if (_CURcdf->status == CDF_READ_ONLY) {
  659.       Tstatus = ReopenCDFforWrite (_CURcdf);
  660.       STATUSdisp (Tstatus, Pstatus);
  661.     }
  662.  
  663.     Var = _CURcdf->CURvar;
  664.  
  665.     if (Var->status == VAR_CLOSED) {
  666.       Tstatus = OpenVar (_CURcdf, Var);
  667.       STATUSdisp (Tstatus, Pstatus);
  668.     }
  669.  
  670.     Var->accessed_at = _CDFpseudo_clock++;
  671.  
  672.     recN = Var->seqValueOffset / Var->NphyRecValues;
  673.  
  674.     if (recN > Var->VDR.MaxRec) {
  675.       if (bitclr(Var->VDR.Flags,VAR_RECVARY_BIT) && recN > 0)
  676.         return END_OF_VAR;
  677.  
  678.       if (_CURcdf->CDR.Version == 1)
  679.         return ILLEGAL_ON_V1_CDF;
  680.  
  681.       Tstatus = AllocateRecords (_CURcdf, Var, recN, FALSE);
  682.       STATUSdisp (Tstatus, Pstatus);
  683.  
  684.       Var->VDR.MaxRec = recN;
  685.       _CURcdf->GDR.MaxRec = Maximum (_CURcdf->GDR.MaxRec, Var->VDR.MaxRec);
  686.     }
  687.  
  688.     if (bitclr(_CURcdf->CDR.Flags,CDF_FORMAT_BIT))
  689.       offset = Var->seqValueOffset * Var->NvalueBytes;
  690.     else {
  691.       SINGLErecOffsetB (Var, recN, recOffset);
  692.       offset = recOffset + (Var->seqValueOffset % Var->NphyRecValues) *
  693.                                                            Var->NvalueBytes;
  694.     }
  695.  
  696. #if defined(sun) | defined(MIPSEB) | defined(IBMRS) | defined(HP)
  697.     Seek (Var->fp, offset, SEEK_SET);
  698.     N = putbytes (Var->NvalueBytes, value, Var->fp);
  699.     if (N != Var->NvalueBytes) return VAR_WRITE_ERROR;
  700. #endif
  701.  
  702. #if defined(vax) | defined(MIPSEL) | defined(__IBMPC__)
  703.     if (_CURcdf->CDR.Encoding == NETWORK_ENCODING) {
  704.       void *tmpbuffer;
  705.       double xdrbuffer;
  706.  
  707.       if (Var->NvalueBytes > sizeof(xdrbuffer)) {
  708.         tmpbuffer = (void *) malloc (Var->NvalueBytes);
  709.         if (tmpbuffer == NULL) return BAD_MALLOC;
  710.       }
  711.       else
  712.         tmpbuffer = (void *) &xdrbuffer;
  713.  
  714.       xdr_encode (Var->VDR.DataType, Var->VDR.NumElem, value, tmpbuffer);
  715.  
  716.       Seek (Var->fp, offset, SEEK_SET);
  717.       N = putbytes (Var->NvalueBytes, tmpbuffer, Var->fp);
  718.       if (N != Var->NvalueBytes) {
  719.         if (tmpbuffer != (void *) &xdrbuffer) free (tmpbuffer);
  720.         return VAR_WRITE_ERROR;
  721.       }
  722.  
  723.       if (tmpbuffer != (void *) &xdrbuffer) free (tmpbuffer);
  724.     }
  725.     else {  /* HOST encoding */
  726.       Seek (Var->fp, offset, SEEK_SET);
  727.       N = putbytes (Var->NvalueBytes, value, Var->fp);
  728.       if (N != Var->NvalueBytes) return VAR_WRITE_ERROR;
  729.     }
  730. #endif
  731.     Var->seqValueOffset++;        /* increment to next value */
  732.  
  733.     break;
  734.   }
  735.  
  736.   case ATTR_SCOPE_: {
  737.     long scope;
  738.  
  739.     scope = va_arg (*ap, long);
  740.  
  741.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  742.     if (_CURcdf->CURattr == NULL) return NO_ATTR_SELECTED;
  743.     if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  744.     if ( ! validAttrScope(scope)) return BAD_SCOPE;
  745.  
  746.     if (_CURcdf->status == CDF_READ_ONLY) {
  747.       Tstatus = ReopenCDFforWrite (_CURcdf);
  748.       STATUSdisp (Tstatus, Pstatus);
  749.     }
  750.  
  751.     _CURcdf->CURattr->ADR.Scope = scope;
  752.  
  753.     break;
  754.   }
  755.   case ATTR_NAME_: {
  756.     /* Make sure no other attribute with this name */
  757.  
  758.     char *attrname;
  759.     char tmpname[CDF_ATTR_NAME_LEN+1];
  760.     struct attrSTRUCT *Attr;
  761.  
  762.     attrname = va_arg (*ap, char *);
  763.  
  764.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  765.     if (_CURcdf->CURattr == NULL) return NO_ATTR_SELECTED;
  766.     if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  767.  
  768.     if (strlen(attrname) > CDF_ATTR_NAME_LEN) {
  769.       strncpy (tmpname, attrname, CDF_ATTR_NAME_LEN);
  770.       tmpname[CDF_ATTR_NAME_LEN] = NUL;
  771.       STATUSdisp (ATTR_NAME_TRUNC, Pstatus);
  772.     }
  773.     else
  774.       strcpy (tmpname, attrname);
  775.  
  776.     if ( ! validAttrName(tmpname)) return BAD_ATTR_NAME;
  777.  
  778.     Attr = _CURcdf->attrHead;
  779.     while (Attr != NULL) {
  780.       if (strcmpITB(tmpname,Attr->ADR.Name) == 0) return ATTR_EXISTS;
  781.       Attr = Attr->attrNext;
  782.     }
  783.  
  784.     if (_CURcdf->status == CDF_READ_ONLY) {
  785.       Tstatus = ReopenCDFforWrite (_CURcdf);
  786.       STATUSdisp (Tstatus, Pstatus);
  787.     }
  788.  
  789.     strcpy (_CURcdf->CURattr->ADR.Name, tmpname);
  790.  
  791.     break;
  792.   }
  793.   case ENTRY_DATA_: {
  794.     long dataType;
  795.     long numElements;
  796.     void *value;
  797.     struct attrSTRUCT *Attr;
  798.     struct entrySTRUCT *Entry;
  799.     struct entrySTRUCT *ntlEntry;          /* next-to-last Entry */
  800.     struct entrySTRUCT *prevEntry;
  801.     long Nbytes;
  802.  
  803.     dataType = va_arg (*ap, long);
  804.     numElements = va_arg (*ap, long);
  805.     value = va_arg (*ap, void *);
  806.  
  807.     if (_CURcdf == NULL) return NO_CDF_SELECTED;
  808.     if (_CURcdf->CURentryNum == RESERVED_ENTRYNUM) return NO_ENTRY_SELECTED;
  809.     if (_CURcdf->CURattr == NULL) return NO_ATTR_SELECTED;
  810.     if (_CURcdf->CDR.Version == 1) return ILLEGAL_ON_V1_CDF;
  811.     if ( ! validDataType(dataType)) return BAD_DATA_TYPE;
  812.     if (numElements < 1) return BAD_NUM_ELEMS;
  813.  
  814.     Nbytes = numElements * _CDFelemSizes[dataType];
  815.  
  816.     if (_CURcdf->status == CDF_READ_ONLY) {
  817.       Tstatus = ReopenCDFforWrite (_CURcdf);
  818.       STATUSdisp (Tstatus, Pstatus);
  819.     }
  820.  
  821.     Attr = _CURcdf->CURattr;
  822.     Entry = _CURcdf->CURentry;
  823.  
  824.     if (Entry == NULL) {          /*** new entry ***/
  825.        Entry = (struct entrySTRUCT *) malloc (sizeof(struct entrySTRUCT));
  826.        if (Entry == NULL) return BAD_MALLOC;
  827.  
  828.        if (Attr->entryHead == NULL) {             /* first entry */
  829.           ntlEntry = (struct entrySTRUCT *) NULL;
  830.           Attr->entryHead = Entry;
  831.           Attr->entryTail = Entry;
  832.        }
  833.        else {
  834.           ntlEntry = _CURcdf->CURattr->entryTail;
  835.           Attr->entryTail->entryNext = Entry;
  836.           Attr->entryTail = Entry;
  837.        }
  838.  
  839.        Entry->entryNext = (struct entrySTRUCT *) NULL;
  840.  
  841.        /*** Set up AEDR ***/
  842.  
  843.        Entry->AEDRoffset = _CURcdf->GDR.eof;
  844.  
  845.        /* RecordSize calculated below */
  846.        Entry->AEDR.RecordType = AEDR_;
  847.        Entry->AEDR.AEDRnext = 0;
  848.        Entry->AEDR.AttrNum = Attr->ADR.Num;
  849.        Entry->AEDR.DataType = dataType;
  850.        Entry->AEDR.Num = _CURcdf->CURentryNum;
  851.        Entry->AEDR.NumElem = numElements;
  852.  
  853.        Entry->AEDR.rfuA = 0;
  854.        Entry->AEDR.rfuB = 0;
  855.        Entry->AEDR.rfuC = 0;
  856.        Entry->AEDR.rfuD = -1;
  857.        Entry->AEDR.rfuE = -1;
  858.  
  859.        Entry->AEDR.Value = (void *) malloc (Nbytes);
  860.        if (Entry->AEDR.Value == NULL) return BAD_MALLOC;  /* CLEAN UP! */
  861.  
  862.        memmove (Entry->AEDR.Value, value, Nbytes);
  863.  
  864.        Entry->AEDR.RecordSize = AEDR_BASE_SIZE + Nbytes;
  865.  
  866.        _CURcdf->GDR.eof += Entry->AEDR.RecordSize;
  867.  
  868.        /*** point next-to-last AEDR (or ADR) to this AEDR ***/
  869.  
  870.        if (ntlEntry == NULL)
  871.           Attr->ADR.AEDRhead = Entry->AEDRoffset;
  872.        else
  873.           ntlEntry->AEDR.AEDRnext = Entry->AEDRoffset;
  874.  
  875.        /*** tally another entry and check if max. entry ***/
  876.  
  877.        Attr->ADR.NumEntries++;
  878.        Attr->ADR.MaxEntry = Maximum (Attr->ADR.MaxEntry, Entry->AEDR.Num);
  879.        _CURcdf->CURentry = Entry;
  880.     }
  881.     else {          /*** entry already exists ***/
  882.       if (Nbytes != Entry->AEDR.NumElem * _CDFelemSizes[Entry->AEDR.DataType]){
  883.         WASTErecord (_CURcdf->fp, Entry->AEDRoffset, Entry->AEDR.RecordSize);
  884.         Entry->AEDRoffset = _CURcdf->GDR.eof;
  885.  
  886.         FINDprevEntry (Attr, Entry, prevEntry);
  887.  
  888.         if (prevEntry == NULL)
  889.           Attr->ADR.AEDRhead = Entry->AEDRoffset;
  890.         else
  891.           prevEntry->AEDR.AEDRnext = Entry->AEDRoffset;
  892.  
  893.         Entry->AEDR.RecordSize = AEDR_BASE_SIZE + Nbytes;
  894.         _CURcdf->GDR.eof += Entry->AEDR.RecordSize;
  895.       }
  896.  
  897.       Entry->AEDR.DataType = dataType;
  898.       Entry->AEDR.NumElem = numElements;
  899.  
  900.       free (Entry->AEDR.Value);
  901.       Entry->AEDR.Value = (void *) malloc (Nbytes);
  902.       if (Entry->AEDR.Value == NULL) return BAD_MALLOC;
  903.  
  904.       memmove (Entry->AEDR.Value, value, Nbytes);
  905.     }
  906.  
  907.     break;
  908.   }
  909.   default: {
  910.     *fnc = item;
  911.     break;
  912.   }
  913. }
  914. return Pstatus;
  915. }
  916.